<template>
	<view class="custom-input-container">
		<slot name="label"></slot>
		<view class="input-wrapper">
			<view class="custom-input" :class="{ focused: isFocused }" contenteditable="true" @tap="handleClick"
				@input="handleCustomInput" ref="customInputRef" v-show="isComponentReady"></view>
			<view class="placeholder" v-if="!hasContent && !isFocused">
				{{ placeholder }}
			</view>
		</view>
		<view class="eye-icon" @tap.stop="togglePasswordVisible">
			<wd-icon :name="isPasswordVisible ? 'eye-close' : 'view'" size="22px"></wd-icon>
		</view>
		<input type="password" class="hidden-input" v-model="nativeValue" @input="handleNativeInput"
			@focus="isFocused = true" @blur="isFocused = false" ref="nativeInputRef" />
	</view>
</template>

<script setup>
	import {
		ref,
		watch,
		onMounted,
		nextTick
	} from 'vue';
	import {
		uniIcons
	} from '@dcloudio/uni-ui';

	const debounce = (fn, delay) => {
		let timer;
		return () => {
			clearTimeout(timer);
			timer = setTimeout(fn, delay);
		};
	};

	const props = defineProps({
		placeholder: {
			type: String,
			default: '请输入密码'
		},
		maxLength: {
			type: Number,
			default: 16
		},
		modelValue: {
			type: String,
			default: ''
		}
	});

	const emit = defineEmits(['update:modelValue', 'input']);

	const customInputRef = ref(null);
	const nativeInputRef = ref(null);
	const nativeValue = ref(props.modelValue);
	const isFocused = ref(false);
	const hasContent = ref(!!props.modelValue);
	const isPasswordVisible = ref(false);
	const isComponentReady = ref(false);

	// 安全设置innerText
	const setDisplayText = (text) => {
		if (customInputRef.value) {
			customInputRef.value.innerText = text;
		}
	};

	// 同步显示文本
	const syncDisplayText = () => {
		const displayText = isPasswordVisible.value ?
			nativeValue.value :
			'•'.repeat(nativeValue.value.length);
		setDisplayText(displayText);
		hasContent.value = nativeValue.value.length > 0;
	};

	// 设置光标到末尾
	const setCursorToEnd = () => {
		if (!customInputRef.value) return;

		try {
			const range = document.createRange();
			const sel = window.getSelection();
			range.selectNodeContents(customInputRef.value);
			range.collapse(false);
			sel.removeAllRanges();
			sel.addRange(range);
		} catch (e) {
			console.log('光标设置失败:', e);
		}
	};

	onMounted(() => {
		nextTick(() => {
			nextTick(() => {
				isComponentReady.value = true;
				syncDisplayText();
				setCursorToEnd(); // 初始化光标位置
			});
		});
	});

	watch(() => props.modelValue, (val) => {
		nativeValue.value = val;
		syncDisplayText();
		setCursorToEnd(); // 外部值变化时光标定位
	});

	const handleClick = () => {
		nextTick(() => {
			nextTick(() => {
				nativeInputRef.value?.focus();
			});
		});
	};

	const handleNativeInput = (e) => {
		const value = e.detail.value.slice(0, props.maxLength);
		nativeValue.value = value;
		syncDisplayText();
		setCursorToEnd(); // 输入时光标定位
		emit('update:modelValue', value);
		emit('input', value);
	};

	const handleCustomInput = debounce(() => {
		if (!customInputRef.value) return;

		const currentDisplay = customInputRef.value.innerText;
		if (!isPasswordVisible.value) {
			nativeValue.value = nativeValue.value.slice(0, currentDisplay.length);
		} else {
			nativeValue.value = currentDisplay.slice(0, props.maxLength);
		}
		hasContent.value = nativeValue.value.length > 0;
		emit('update:modelValue', nativeValue.value);
		setCursorToEnd(); // 手动修改时光标定位
	}, 100);

	const togglePasswordVisible = () => {
		isPasswordVisible.value = !isPasswordVisible.value;
		syncDisplayText();
		nextTick(() => {
			nativeInputRef.value?.focus();
			setCursorToEnd(); // 切换可见性时光标定位
		});
	};

	defineExpose({
		focus: () => {
			nativeInputRef.value?.focus();
			setCursorToEnd();
		},
		getValue: () => nativeValue.value
	});
</script>

<style scoped>
	.custom-input-container {
		display: flex;
		align-items: center;
		width: 100%;
		padding: 0 20rpx;
		margin-bottom: 30rpx;
	}

	::v-deep .custom-input-container>slot[name="label"] {
		width: 140rpx;
		font-size: 32rpx;
		margin-right: 10rpx;
	}

	.input-wrapper {
		flex: 1;
		position: relative;
		min-height: 80rpx;
	}

	.custom-input {
		width: 100%;
		padding: 16rpx 24rpx;
		/* 上下内边距确保垂直居中 */
		border: 2rpx solid #e5e5e5;
		border-radius: 40rpx;
		background-color: #f5f5f5;
		font-size: 32rpx;
		outline: none;
		box-sizing: border-box;
		-webkit-user-modify: read-write-plaintext-only;
		caret-color: #07c160;

		/* 新增：弹性布局垂直居中 */
		display: flex;
		align-items: center;
		line-height: normal;
		vertical-align: middle;
		min-height: 80rpx;
		height: auto;
	}

	.custom-input::before {
		/* 新增：解决行高问题的幽灵节点 */
		content: '';
		display: inline-block;
		vertical-align: middle;
		height: 100%;
	}

	.custom-input.focused {
		border-color: #07c160;
	}

	.placeholder {
		position: absolute;
		left: 24rpx;
		top: 50%;
		transform: translateY(-50%);
		font-size: 32rpx;
		color: #999;
		pointer-events: none;
	}

	.eye-icon {
		width: 60rpx;
		height: 80rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		margin-left: 10rpx;
		cursor: pointer;
	}

	.hidden-input {
		position: absolute;
		left: -9999rpx;
		top: -9999rpx;
		width: 1px;
		height: 1px;
		opacity: 0;
		border: none;
		pointer-events: none;
	}
</style>